package com.hq.ims.userpc.busservice;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.hq.authority.utils.AppUtils;
import com.hq.ims.data.config.verification.VdAdd;
import com.hq.ims.data.config.verification.VdEdit;
import com.hq.ims.data.entity.*;
import com.hq.ims.data.entityenum.*;
import com.hq.ims.data.event.BusinfoEvent;
import com.hq.ims.data.service.*;
import com.hq.ims.data.utils.ErrMsgConstant;
import com.hq.ims.data.utils.LocalConstant;
import com.hq.ims.data.utils.WebExpandUtils;
import com.hq.ims.data.vo.*;
import com.hq.utils.util.ObjectUtils;
import com.hq.utils.util.StringUtils;
import com.hq.web.utils.SpringBootValidateUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yinzhangxiao
 * @date 2024/10/30 10:51
 * @ClassName UserBusInfoService
 **/
@Service
public class UserBusiInfoService {
    @Resource
    private BaseBusiHistoryService baseBusiHistoryService;
    @Resource
    private BaseBusInfoTrackService baseBusInfoTrackService;
    @Resource
    private ApplicationContext applicationContext;
    @Resource
    private BaseCompanyService baseCompanyService;
    @Resource
    private BaseBusiIndustryCompanyService baseBusiIndustryCompanyService;
    @Resource
    private BaseBusiChangeService baseBusiChangeService;
    @Resource
    private BaseBusiInfoService baseBusiInfoService;

    /**
     * @description: 新增经营信息
     * @author: yinzhangxiao
     * @date: 2024/11/15 14:58
     */
    @Transactional(rollbackFor = Exception.class)
    public String addBusiInfo(BusiInfoMapstruct.SaveVo vo) {
        //验证数据是否为空
        SpringBootValidateUtils.validate(vo, VdAdd.class);
        //校验数据
        baseBusiInfoService.validate(null,vo,LocalConstant.INSERT);
        //查询省市code
        baseBusiInfoService.setAreaCode(vo);
        //补全数据
        vo.setOrgId(WebExpandUtils.getHeadCompanyId());
        vo.setPublisherId(AppUtils.getUserId());
        vo.setPublisher(AppUtils.getCurrentUser().getRealName());
        vo.setPublishStatus(EnumPublishStatus.Unreleased);
        vo.setPublishTime(LocalDateTime.now());
        vo.setAuditStatus(EnumAuditStatus.UnderReview);
        vo.setAcceptStatus(EnumReceiveStatus.UnReceive);
        vo.setContactPerson(AppUtils.getCurrentUser().getRealName());
        vo.setContactInfomation(AppUtils.getCurrentUser().getMobile());
        vo.setCreateDateTime(LocalDateTime.now());
        vo.setUpdateDateTime(LocalDateTime.now());
        vo.setCreateUserName(AppUtils.getCurrentUser().getRealName());
        vo.setUpdateUserName(AppUtils.getCurrentUser().getRealName());
        //拼接信息表产业标记字段
        baseBusiInfoService.setBusiIndustryAssign(vo);
        //设置企业分成规则
        Company company = baseCompanyService.lambdaQuery()
                .select(Company::getCompanyDivideIntoRuleValue)
                .eq(Company::getCompanyId, WebExpandUtils.getHeadCompanyId())
                .one();
        if (company != null) {
            vo.setCompanyDivideIntoRuleValue(company.getCompanyDivideIntoRuleValue());
        }
        BusiInfo busiInfo = baseBusiInfoService.addData(vo);
        vo.setBusiInfoId(busiInfo.getBusiInfoId());
        //计算相似度
        BigDecimal repetitionRate = baseBusiInfoService.calcSimilarityRate(vo);
        busiInfo.setRepetitionRate(repetitionRate.setScale(0, RoundingMode.HALF_UP).doubleValue());
        if (StringUtils.isNotEmpty(vo.getParentId()) && !"0".equals(vo.getParentId())) {
            BusiInfo parentBusiInfo = baseBusiInfoService.getById(vo.getParentId());
            busiInfo.setRootId(parentBusiInfo.getRootId());
            busiInfo.setInfoType(EnumBusinessTypeStatus.ProfessionRelevance);
        } else {
            busiInfo.setRootId(busiInfo.getBusiInfoId());
            busiInfo.setParentId("0");
            busiInfo.setInfoType(EnumBusinessTypeStatus.AllUserBusiness);
        }
        busiInfo.setVersion(0);
        baseBusiInfoService.updateById(busiInfo);
        //保存产业标记指派以及补全并保存产业标记公司
        baseBusiInfoService.saveBusiIndustryAssignList(vo);
        //插入历史表
        BusiHistoryMapstruct.SaveVo build = new BusiHistoryMapstruct.SaveVo();
        BeanUtils.copyProperties(busiInfo, build);
        baseBusiHistoryService.addData(build);
        //发布事件
        applicationContext.publishEvent(new BusinfoEvent(this, busiInfo, BusinfoEvent.ADD_EVENT));
        //返回值
        return busiInfo.getBusiInfoId();
    }

    /**
     * @description: 编辑经营信息
     * @author: yinzhangxiao
     * @date: 2024/11/15 14:59
     */
    @Transactional(rollbackFor = Exception.class)
    public void editBusiInfo(BusiInfoMapstruct.SaveVo vo) {
        //验证数据是否为空
        SpringBootValidateUtils.validate(vo, VdEdit.class);
        //验证数据是否存在
        BusiInfo entity = baseBusiInfoService.getDetailVo(vo.getBusiInfoId());
        ObjectUtils.isNullThrow(entity, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        //校验数据
        baseBusiInfoService.validate(entity,vo,LocalConstant.EDIT);
        //查询省市code
        baseBusiInfoService.setAreaCode(vo);
        //重新设置审核状态、接收状态、企业分成规则
        vo.setAuditStatus(EnumAuditStatus.UnderReview);
        vo.setAcceptStatus(EnumReceiveStatus.UnReceive);
        //计算相似度
        BigDecimal repetitionRate = baseBusiInfoService.calcSimilarityRate(vo);
        vo.setRepetitionRate(repetitionRate.setScale(0, RoundingMode.HALF_UP).doubleValue());
        //设置企业分成规则
        Company company = baseCompanyService.lambdaQuery()
                .select(Company::getCompanyDivideIntoRuleValue)
                .eq(Company::getCompanyId, WebExpandUtils.getHeadCompanyId())
                .one();
        if (company != null) {
            vo.setCompanyDivideIntoRuleValue(company.getCompanyDivideIntoRuleValue());
        }
        BusiInfoMapstruct.SaveVo oldSaveVo = new BusiInfoMapstruct.SaveVo();
        BeanUtils.copyProperties(entity,oldSaveVo);
        //设置产业标记字段
        baseBusiInfoService.setBusiIndustryAssign(vo);
        //比较变更数据
        List<Map<String, Object>> maps = baseBusiInfoService.compareFields(oldSaveVo, vo);
        baseBusiInfoService.compareIndustry(vo,maps);
        vo.setUpdateDateTime(LocalDateTime.now());
        vo.setUpdateUserName(AppUtils.getCurrentUser().getRealName());
        BusiInfo busiInfo = baseBusiInfoService.editData(vo);
        //保存产业标记指派以及补全并保存产业标记公司
        baseBusiInfoService.saveBusiIndustryAssignList(vo);
        //插入信息变更历史
        baseBusiHistoryService.saveBusiChangeTimeRecord(busiInfo);
        if (CollectionUtils.isNotEmpty(maps)){
            List<BusiChange> changeList = new ArrayList<>(maps.size());
            maps.forEach(map->{
                BusiChange busiChange = new BusiChange();
                busiChange.setBusiInfoId(vo.getBusiInfoId());
                busiChange.setChangeContent(MapUtils.getString(map,"name"));
                busiChange.setChangeBefore(MapUtils.getString(map,"changeBefore"));
                busiChange.setChangeAfter(MapUtils.getString(map,"changeAfter"));
                busiChange.setChangeTime(LocalDateTime.now());
                busiChange.setChangeWay(EnumChangeWay.UserChange);
                changeList.add(busiChange);
            });
            baseBusiChangeService.saveBatch(changeList);
        }
        //发布事件
        applicationContext.publishEvent(new BusinfoEvent(this, busiInfo, BusinfoEvent.EDIT_EVENT));
        //返回值

    }

    /**
     * @description: 用户端查看源信息
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:08
     */
    public BusiInfoMapstruct.BusiInfoVo getRootData(String parentId) {
        BusiInfo parentBusiInfo = baseBusiInfoService.getById(parentId);
        ObjectUtils.isNullThrow(parentBusiInfo, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        BusiInfoMapstruct.BusiInfoVo busiInfoVo = BusiInfoMapstruct.INSTANCE.toBusiInfoVo(parentBusiInfo);
        //拼接源信息的派生信息，查询范围根据组织向下查询
        List<Company> allChildrenCompanyList = baseCompanyService.getAllChildrenCompanyList(Objects.requireNonNull(WebExpandUtils.getHeadCompanyId()), true);
        List<String> orgIds = allChildrenCompanyList.stream().map(Company::getCompanyId).collect(Collectors.toList());
        List<BusiInfo> list = baseBusiInfoService.lambdaQuery()
                .eq(BusiInfo::getParentId, parentBusiInfo.getBusiInfoId())
                .in(BusiInfo::getOrgId, orgIds)
                .list();
        busiInfoVo.setDerivativeList(list);
        return busiInfoVo;
    }

    /**
     * @description: 产业链关联查询信息列表
     * @author: yinzhangxiao
     * @date: 2024/11/15 15:09
     */
    public List<BusiInfoMapstruct.BusiInfoVo> professionRelevanceList(String keyWord) {
        //查询我的跟踪列表
        List<BusInfoTrack> busInfoTrackList = baseBusInfoTrackService.lambdaQuery()
                .select(BusInfoTrack::getBusiInfoId)
                .eq(BusInfoTrack::getBusiPersonId, AppUtils.getUserId())
                .list();
        //查询经营信息列表
        LambdaQueryChainWrapper<BusiInfo> lq = baseBusiInfoService.lambdaQuery();
        lq.eq(BusiInfo::getAuditStatus, EnumAuditStatus.Pass);
        //查询我跟踪的经营信息或我发布的经营信息
        lq.and(wrapper -> wrapper
                .in(CollectionUtils.isNotEmpty(busInfoTrackList), BusiInfo::getBusiInfoId, busInfoTrackList.stream()
                        .map(BusInfoTrack::getBusiInfoId)
                        .distinct()
                        .collect(Collectors.toList()))
                .or().eq(BusiInfo::getPublisherId, AppUtils.getUserId()));
        // 根据关键字筛选过滤
        if (StringUtils.isNotEmpty(keyWord)) {
            lq.and(wrapper -> wrapper.like(BusiInfo::getProjectName, keyWord)
                    .or().like(BusiInfo::getIndustryAssign, keyWord)
                    .or().like(BusiInfo::getProvince, keyWord)
                    .or().like(BusiInfo::getCity, keyWord)
                    .or().like(BusiInfo::getProjectAddressName, keyWord)
                    .or().like(BusiInfo::getOwnerCompanyName, keyWord)
                    .or().like(BusiInfo::getConstructionName, keyWord)
            );
        }
        return BusiInfoMapstruct.INSTANCE.toBusiInfoVoList(lq.list());
    }

    /**
     * @description: 撤销经营信息
     * @author: yinzhangxiao
     * @date: 2024/12/02 08:51
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelData(String busiInfoId) {
        //验证数据是否存在
        BusiInfo entity = baseBusiInfoService.getById(busiInfoId);
        ObjectUtils.isNullThrow(entity, ErrMsgConstant.PROJECT_INFO_NOT_EXITS);
        EnumAuditStatus.isCanCancelTh(entity.getAuditStatus());
        entity.setAuditStatus(EnumAuditStatus.CancelAudit);
        entity.setUpdateDateTime(LocalDateTime.now());
        entity.setUpdateUserName(AppUtils.getCurrentUser().getRealName());
        baseBusiInfoService.updateById(entity);
        //撤销删除系统生成指派公司
        baseBusiIndustryCompanyService.lambdaUpdate()
                .eq(BusiIndustryCompany::getBusiInfoId,busiInfoId)
                .eq(BusiIndustryCompany::getNotificationWay, EnumNotificationWay.Sysgenerated)
                .remove();

        //发送撤销事件
        //发布事件
        this.applicationContext.publishEvent(new BusinfoEvent(this, entity, BusinfoEvent.CANCEL_BUSINFO_AUDIT));
    }
}
